import React, { useMemo } from 'react';
import { Button, Divider } from 'antd';

// pure shouldComponent
// useMemo memo useCallback
// immutable immer

export default function RenderDemo() {
  return (
    <div>
      <ClassDemo />
      <Divider />
      <FuncDemo />
    </div>
  );
}

// 函数子组件渲染
function Children(props: any) {
  console.log('子组件Children渲染');
  return <div style={{ marginBottom: '20px' }}> func {props.number} </div>;
}

// 函数组件就使用
// memo 第二个参数 返回 true 组件不渲染 ， 返回 false 组件重新渲染 默认是浅比较
const MemoChildren = React.memo(Children);

// 类组件的子组件渲染
class ClassChildren extends React.Component<any, any, any> {
  render() {
    console.log('ClassChildren render');
    return <div style={{ marginBottom: '20px' }}> classComponent {this.props.number} </div>;
  }
}

// 类组件使用 PureComponent
// 比较state和props
class ClassChildren1 extends React.PureComponent<any, any, any> {
  // forceUpdate context
  render() {
    console.log('ClassChildren1 render');
    return <div style={{ marginBottom: '20px' }}> classComponent {this.props.number} </div>;
  }
}

// 类组件通过 shouldComponentUpdate 来控制
class ClassChildren2 extends React.Component<any, any, any> {
  // 自己来判断
  shouldComponentUpdate(newProp: any) {
    if (newProp.number !== this.props.number) {
      return true;
    }
    return false;
  }
  render() {
    console.log('ClassChildren2 render');
    return <div style={{ marginBottom: '20px' }}> classComponent {this.props.number} </div>;
  }
}

// 父组件是类组件的情况
class ClassDemo extends React.Component<any, any, any> {
  component: any;
  constructor(props: any) {
    super(props);
    this.state = {
      numberA: 0,
      numberB: 0,
    };
    this.component = <Children number={this.state.numberA} />;
  }
  controlComponentRender = () => {
    const { props } = this.component;
    if (props.number !== this.state.numberA) {
      // 值不想等的就clone一个 修改props属性值
      return (this.component = React.cloneElement(this.component, { number: this.state.numberA }));
    }
    // 相等的时候
    return this.component;
  };

  handleChange = () => {
    console.log('handleChange');
  };
  // 2 * 2 = 4
  render() {
    return (
      <div>
        {/* 子组件为函数组件的情况 */}
        <Children number={this.state.numberA} />
        <MemoChildren number={this.state.numberA} />
        {/* 自己控制渲染的逻辑 */}
        {this.controlComponentRender()}

        {/* 子组件为类组件的情况 */}
        <ClassChildren number={this.state.numberA} />
        <ClassChildren1
          number={this.state.numberA}
          change={this.handleChange}
          // 不要使用箭头函数 每次都是最新的
          callback={() => {}}
        />
        <ClassChildren2 number={this.state.numberA} />

        <Button.Group>
          <Button
            onClick={() => this.setState({ numberA: this.state.numberA + 1 })}
            style={{ marginRight: '10px' }}
          >
            改变numberA
          </Button>
          <Button onClick={() => this.setState({ numberB: this.state.numberB + 1 })}>
            改变numberB
          </Button>
        </Button.Group>
      </div>
    );
  }
}

// 父组件是函数组件的时候 函数的传递也需要特别的小心
// 使用 useCallback和useMemo
// https://ahooks.js.org/zh-CN/hooks/use-why-did-you-update
// Object.is
// https://github.com/alibaba/hooks/blob/master/packages/hooks/src/useWhyDidYouUpdate/index.ts
function FuncDemo() {
  const [numberA, setNumberA] = React.useState(0);
  const [numberB, setNumberB] = React.useState(0);

  const handleClick = () => {
    console.log('handleClick');
  };

  const callbackHandleCLick = React.useCallback(handleClick, []);

  const memoHandleCLick = React.useMemo(handleClick, []);

  return (
    <>
      <div style={{ marginBottom: '20px' }}> 父组件改变props </div>
      <Button onClick={() => setNumberA(numberA + 1)} style={{ marginRight: '10px' }}>
        改变numberA
      </Button>
      <Button onClick={() => setNumberB(numberB + 1)} style={{ marginBottom: '20px' }}>
        改变numberB
      </Button>

      <Child number={numberA} />
      <MemoChild number={numberA} />

      {useMemo(
        () => (
          <Children number={numberA} />
        ),
        [numberA],
      )}

      {/* 函数组件传递的函数都是新的函数 */}
      <MemoChildren number={numberA} />
      <MemoChildren number={numberA} handleClick={handleClick} />
      <MemoChildren number={numberA} handleClick={memoHandleCLick} />
      <MemoChildren number={numberA} handleClick={callbackHandleCLick} />
    </>
  );
}

function Child(props: any) {
  console.log('memo demo render');
  return <div>hello,world: {props.number} </div>;
}

// number不改变或number 改变但值大于5->不渲染组件 | 否则渲染组件
const controlIsRender = (pre: any, next: any) => {
  return pre.number === next.number || (pre.number !== next.number && next.number > 5);
};

// 自己传入比较的方法
const MemoChild = React.memo(Child, controlIsRender);
